package com.kexilo.messaging.properties;

import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;

/**
 * 消息处理插件配置属性
 * 提供完善的配置选项和IDE智能提示
 * 
 * @author Kexilo
 */
@ConfigurationProperties(prefix = "kexilo.plugin.messaging")
public class MessageProperties {
    
    /**
     * 消息中间件类型
     */
    public enum MiddlewareType {
        MEMORY,     // 内存消息队列
        REDIS,      // Redis消息队列
        RABBITMQ,   // RabbitMQ
        KAFKA,      // Apache Kafka
        ROCKETMQ,   // Apache RocketMQ
        ACTIVEMQ    // Apache ActiveMQ
    }
    
    /**
     * 序列化方式
     */
    public enum SerializationType {
        JSON,       // JSON序列化
        PROTOBUF,   // Protocol Buffers
        AVRO,       // Apache Avro
        KRYO,       // Kryo
        JDK         // JDK原生序列化
    }
    
    /**
     * 消费模式
     */
    public enum ConsumerMode {
        PUSH,       // 推送模式
        PULL,       // 拉取模式
        BOTH        // 混合模式
    }
    
    /**
     * 是否启用消息插件
     */
    private boolean enabled = true;
    
    /**
     * 中间件类型
     */
    private MiddlewareType middlewareType = MiddlewareType.MEMORY;
    
    /**
     * 序列化类型
     */
    private SerializationType serializationType = SerializationType.JSON;
    
    /**
     * 消费模式
     */
    private ConsumerMode consumerMode = ConsumerMode.PUSH;
    
    /**
     * 默认主题前缀
     */
    private String topicPrefix = "kexilo";
    
    /**
     * 是否启用消息持久化
     */
    private boolean persistenceEnabled = true;
    
    /**
     * 是否启用消息压缩
     */
    private boolean compressionEnabled = false;
    
    /**
     * 是否启用死信队列
     */
    private boolean deadLetterQueueEnabled = true;
    
    /**
     * 是否启用重试机制
     */
    private boolean retryEnabled = true;
    
    /**
     * 是否启用事务消息
     */
    private boolean transactionEnabled = false;
    
    /**
     * 生产者配置
     */
    @Valid
    @NestedConfigurationProperty
    private ProducerProperties producer = new ProducerProperties();
    
    /**
     * 消费者配置
     */
    @Valid
    @NestedConfigurationProperty
    private ConsumerProperties consumer = new ConsumerProperties();
    
    /**
     * 重试配置
     */
    @Valid
    @NestedConfigurationProperty
    private RetryProperties retry = new RetryProperties();
    
    /**
     * 死信队列配置
     */
    @Valid
    @NestedConfigurationProperty
    private DeadLetterProperties deadLetter = new DeadLetterProperties();
    
    /**
     * 监控配置
     */
    @Valid
    @NestedConfigurationProperty
    private MonitorProperties monitor = new MonitorProperties();
    
    /**
     * 邮件配置
     */
    @Valid
    @NestedConfigurationProperty
    private EmailProperties email = new EmailProperties();
    
    /**
     * 短信配置
     */
    @Valid
    @NestedConfigurationProperty
    private SmsProperties sms = new SmsProperties();
    
    /**
     * 推送配置
     */
    @Valid
    @NestedConfigurationProperty
    private PushProperties push = new PushProperties();
    
    /**
     * 主题配置
     */
    private Map<String, TopicProperties> topics = new HashMap<>();
    
    /**
     * 生产者配置属性
     */
    public static class ProducerProperties {
        /**
         * 是否启用生产者
         */
        private boolean enabled = true;
        
        /**
         * 生产者线程池大小
         */
        @Min(value = 1, message = "生产者线程池大小必须大于0")
        private int threadPoolSize = 3;
        
        /**
         * 发送超时时间
         */
        private Duration sendTimeout = Duration.ofSeconds(30);
        
        /**
         * 批量发送大小
         */
        @Min(value = 1, message = "批量发送大小必须大于0")
        private int batchSize = 100;
        
        /**
         * 批量发送等待时间
         */
        private Duration batchWaitTime = Duration.ofMillis(100);
        
        /**
         * 最大消息大小
         */
        private String maxMessageSize = "4MB";
        
        /**
         * 是否启用消息确认
         */
        private boolean ackEnabled = true;
        
        /**
         * 确认超时时间
         */
        private Duration ackTimeout = Duration.ofSeconds(10);
        
        // Getters and Setters
        public boolean isEnabled() { return enabled; }
        public void setEnabled(boolean enabled) { this.enabled = enabled; }
        
        public int getThreadPoolSize() { return threadPoolSize; }
        public void setThreadPoolSize(int threadPoolSize) { this.threadPoolSize = threadPoolSize; }
        
        public Duration getSendTimeout() { return sendTimeout; }
        public void setSendTimeout(Duration sendTimeout) { this.sendTimeout = sendTimeout; }
        
        public int getBatchSize() { return batchSize; }
        public void setBatchSize(int batchSize) { this.batchSize = batchSize; }
        
        public Duration getBatchWaitTime() { return batchWaitTime; }
        public void setBatchWaitTime(Duration batchWaitTime) { this.batchWaitTime = batchWaitTime; }
        
        public String getMaxMessageSize() { return maxMessageSize; }
        public void setMaxMessageSize(String maxMessageSize) { this.maxMessageSize = maxMessageSize; }
        
        public boolean isAckEnabled() { return ackEnabled; }
        public void setAckEnabled(boolean ackEnabled) { this.ackEnabled = ackEnabled; }
        
        public Duration getAckTimeout() { return ackTimeout; }
        public void setAckTimeout(Duration ackTimeout) { this.ackTimeout = ackTimeout; }
    }
    
    /**
     * 消费者配置属性
     */
    public static class ConsumerProperties {
        /**
         * 是否启用消费者
         */
        private boolean enabled = true;
        
        /**
         * 消费者线程池大小
         */
        @Min(value = 1, message = "消费者线程池大小必须大于0")
        private int threadPoolSize = 5;
        
        /**
         * 拉取消息数量
         */
        @Min(value = 1, message = "拉取消息数量必须大于0")
        private int pullBatchSize = 10;
        
        /**
         * 拉取超时时间
         */
        private Duration pullTimeout = Duration.ofSeconds(10);
        
        /**
         * 消费超时时间
         */
        private Duration consumeTimeout = Duration.ofMinutes(5);
        
        /**
         * 是否启用并发消费
         */
        private boolean concurrentConsumingEnabled = true;
        
        /**
         * 并发消费数量
         */
        @Min(value = 1, message = "并发消费数量必须大于0")
        private int concurrentConsumingCount = 10;
        
        /**
         * 是否启用顺序消费
         */
        private boolean orderedConsumingEnabled = false;
        
        // Getters and Setters
        public boolean isEnabled() { return enabled; }
        public void setEnabled(boolean enabled) { this.enabled = enabled; }
        
        public int getThreadPoolSize() { return threadPoolSize; }
        public void setThreadPoolSize(int threadPoolSize) { this.threadPoolSize = threadPoolSize; }
        
        public int getPullBatchSize() { return pullBatchSize; }
        public void setPullBatchSize(int pullBatchSize) { this.pullBatchSize = pullBatchSize; }
        
        public Duration getPullTimeout() { return pullTimeout; }
        public void setPullTimeout(Duration pullTimeout) { this.pullTimeout = pullTimeout; }
        
        public Duration getConsumeTimeout() { return consumeTimeout; }
        public void setConsumeTimeout(Duration consumeTimeout) { this.consumeTimeout = consumeTimeout; }
        
        public boolean isConcurrentConsumingEnabled() { return concurrentConsumingEnabled; }
        public void setConcurrentConsumingEnabled(boolean concurrentConsumingEnabled) { this.concurrentConsumingEnabled = concurrentConsumingEnabled; }
        
        public int getConcurrentConsumingCount() { return concurrentConsumingCount; }
        public void setConcurrentConsumingCount(int concurrentConsumingCount) { this.concurrentConsumingCount = concurrentConsumingCount; }
        
        public boolean isOrderedConsumingEnabled() { return orderedConsumingEnabled; }
        public void setOrderedConsumingEnabled(boolean orderedConsumingEnabled) { this.orderedConsumingEnabled = orderedConsumingEnabled; }
    }
    
    /**
     * 重试配置属性
     */
    public static class RetryProperties {
        /**
         * 最大重试次数
         */
        @Min(value = 0, message = "最大重试次数不能小于0")
        private int maxRetries = 3;
        
        /**
         * 重试间隔
         */
        private Duration retryInterval = Duration.ofSeconds(30);
        
        /**
         * 重试倍数（指数退避）
         */
        private double retryMultiplier = 2.0;
        
        /**
         * 最大重试间隔
         */
        private Duration maxRetryInterval = Duration.ofMinutes(30);
        
        /**
         * 重试队列名称
         */
        private String retryQueueName = "retry-queue";
        
        // Getters and Setters
        public int getMaxRetries() { return maxRetries; }
        public void setMaxRetries(int maxRetries) { this.maxRetries = maxRetries; }
        
        public Duration getRetryInterval() { return retryInterval; }
        public void setRetryInterval(Duration retryInterval) { this.retryInterval = retryInterval; }
        
        public double getRetryMultiplier() { return retryMultiplier; }
        public void setRetryMultiplier(double retryMultiplier) { this.retryMultiplier = retryMultiplier; }
        
        public Duration getMaxRetryInterval() { return maxRetryInterval; }
        public void setMaxRetryInterval(Duration maxRetryInterval) { this.maxRetryInterval = maxRetryInterval; }
        
        public String getRetryQueueName() { return retryQueueName; }
        public void setRetryQueueName(String retryQueueName) { this.retryQueueName = retryQueueName; }
    }
    
    /**
     * 死信队列配置属性
     */
    public static class DeadLetterProperties {
        /**
         * 死信队列名称
         */
        private String queueName = "dead-letter-queue";
        
        /**
         * 死信消息保留时间
         */
        private Duration retentionTime = Duration.ofDays(7);
        
        /**
         * 最大死信消息数量
         */
        @Min(value = 1, message = "最大死信消息数量必须大于0")
        private int maxMessages = 10000;
        
        /**
         * 是否自动清理过期消息
         */
        private boolean autoCleanupEnabled = true;
        
        /**
         * 清理间隔
         */
        private Duration cleanupInterval = Duration.ofHours(1);
        
        // Getters and Setters
        public String getQueueName() { return queueName; }
        public void setQueueName(String queueName) { this.queueName = queueName; }
        
        public Duration getRetentionTime() { return retentionTime; }
        public void setRetentionTime(Duration retentionTime) { this.retentionTime = retentionTime; }
        
        public int getMaxMessages() { return maxMessages; }
        public void setMaxMessages(int maxMessages) { this.maxMessages = maxMessages; }
        
        public boolean isAutoCleanupEnabled() { return autoCleanupEnabled; }
        public void setAutoCleanupEnabled(boolean autoCleanupEnabled) { this.autoCleanupEnabled = autoCleanupEnabled; }
        
        public Duration getCleanupInterval() { return cleanupInterval; }
        public void setCleanupInterval(Duration cleanupInterval) { this.cleanupInterval = cleanupInterval; }
    }
    
    /**
     * 监控配置属性
     */
    public static class MonitorProperties {
        /**
         * 是否启用监控
         */
        private boolean enabled = true;
        
        /**
         * 监控数据收集间隔
         */
        private Duration collectInterval = Duration.ofMinutes(1);
        
        /**
         * 监控数据保留时间
         */
        private Duration dataRetentionTime = Duration.ofDays(7);
        
        /**
         * 是否启用性能监控
         */
        private boolean performanceMonitorEnabled = true;
        
        /**
         * 慢消息阈值
         */
        private Duration slowMessageThreshold = Duration.ofSeconds(5);
        
        /**
         * 是否启用告警
         */
        private boolean alertEnabled = true;
        
        /**
         * 消费延迟告警阈值
         */
        private Duration consumeLagAlertThreshold = Duration.ofMinutes(10);
        
        // Getters and Setters
        public boolean isEnabled() { return enabled; }
        public void setEnabled(boolean enabled) { this.enabled = enabled; }
        
        public Duration getCollectInterval() { return collectInterval; }
        public void setCollectInterval(Duration collectInterval) { this.collectInterval = collectInterval; }
        
        public Duration getDataRetentionTime() { return dataRetentionTime; }
        public void setDataRetentionTime(Duration dataRetentionTime) { this.dataRetentionTime = dataRetentionTime; }
        
        public boolean isPerformanceMonitorEnabled() { return performanceMonitorEnabled; }
        public void setPerformanceMonitorEnabled(boolean performanceMonitorEnabled) { this.performanceMonitorEnabled = performanceMonitorEnabled; }
        
        public Duration getSlowMessageThreshold() { return slowMessageThreshold; }
        public void setSlowMessageThreshold(Duration slowMessageThreshold) { this.slowMessageThreshold = slowMessageThreshold; }
        
        public boolean isAlertEnabled() { return alertEnabled; }
        public void setAlertEnabled(boolean alertEnabled) { this.alertEnabled = alertEnabled; }
        
        public Duration getConsumeLagAlertThreshold() { return consumeLagAlertThreshold; }
        public void setConsumeLagAlertThreshold(Duration consumeLagAlertThreshold) { this.consumeLagAlertThreshold = consumeLagAlertThreshold; }
    }
    
    /**
     * 邮件配置属性
     */
    public static class EmailProperties {
        /**
         * 是否启用邮件消息
         */
        private boolean enabled = false;
        
        /**
         * 默认发件人
         */
        private String defaultSender = "system@kexilo.com";
        
        /**
         * 邮件模板路径
         */
        private String templatePath = "classpath:mail-templates/";
        
        /**
         * 默认邮件模板
         */
        private String defaultTemplate = "default";
        
        // Getters and Setters
        public boolean isEnabled() { return enabled; }
        public void setEnabled(boolean enabled) { this.enabled = enabled; }
        
        public String getDefaultSender() { return defaultSender; }
        public void setDefaultSender(String defaultSender) { this.defaultSender = defaultSender; }
        
        public String getTemplatePath() { return templatePath; }
        public void setTemplatePath(String templatePath) { this.templatePath = templatePath; }
        
        public String getDefaultTemplate() { return defaultTemplate; }
        public void setDefaultTemplate(String defaultTemplate) { this.defaultTemplate = defaultTemplate; }
    }
    
    /**
     * 短信配置属性
     */
    public static class SmsProperties {
        /**
         * 是否启用短信消息
         */
        private boolean enabled = false;
        
        /**
         * 短信提供商
         */
        private String provider = "aliyun";
        
        /**
         * AccessKey ID
         */
        private String accessKeyId;
        
        /**
         * AccessKey Secret
         */
        private String accessKeySecret;
        
        /**
         * 短信签名
         */
        private String signName = "Kexilo";
        
        // Getters and Setters
        public boolean isEnabled() { return enabled; }
        public void setEnabled(boolean enabled) { this.enabled = enabled; }
        
        public String getProvider() { return provider; }
        public void setProvider(String provider) { this.provider = provider; }
        
        public String getAccessKeyId() { return accessKeyId; }
        public void setAccessKeyId(String accessKeyId) { this.accessKeyId = accessKeyId; }
        
        public String getAccessKeySecret() { return accessKeySecret; }
        public void setAccessKeySecret(String accessKeySecret) { this.accessKeySecret = accessKeySecret; }
        
        public String getSignName() { return signName; }
        public void setSignName(String signName) { this.signName = signName; }
    }
    
    /**
     * 推送配置属性
     */
    public static class PushProperties {
        /**
         * 是否启用推送消息
         */
        private boolean enabled = false;
        
        /**
         * 推送提供商
         */
        private String provider = "fcm";
        
        /**
         * 服务密钥文件路径
         */
        private String serviceKeyPath;
        
        /**
         * 项目ID
         */
        private String projectId;
        
        // Getters and Setters
        public boolean isEnabled() { return enabled; }
        public void setEnabled(boolean enabled) { this.enabled = enabled; }
        
        public String getProvider() { return provider; }
        public void setProvider(String provider) { this.provider = provider; }
        
        public String getServiceKeyPath() { return serviceKeyPath; }
        public void setServiceKeyPath(String serviceKeyPath) { this.serviceKeyPath = serviceKeyPath; }
        
        public String getProjectId() { return projectId; }
        public void setProjectId(String projectId) { this.projectId = projectId; }
    }
    
    /**
     * 主题配置属性
     */
    public static class TopicProperties {
        /**
         * 分区数
         */
        @Min(value = 1, message = "分区数必须大于0")
        private int partitions = 1;
        
        /**
         * 副本数
         */
        @Min(value = 1, message = "副本数必须大于0")
        private int replicas = 1;
        
        /**
         * 消息保留时间
         */
        private Duration retentionTime = Duration.ofDays(7);
        
        /**
         * 是否启用压缩
         */
        private boolean compressionEnabled = false;
        
        // Getters and Setters
        public int getPartitions() { return partitions; }
        public void setPartitions(int partitions) { this.partitions = partitions; }
        
        public int getReplicas() { return replicas; }
        public void setReplicas(int replicas) { this.replicas = replicas; }
        
        public Duration getRetentionTime() { return retentionTime; }
        public void setRetentionTime(Duration retentionTime) { this.retentionTime = retentionTime; }
        
        public boolean isCompressionEnabled() { return compressionEnabled; }
        public void setCompressionEnabled(boolean compressionEnabled) { this.compressionEnabled = compressionEnabled; }
    }
    
    // Main class Getters and Setters
    public boolean isEnabled() { return enabled; }
    public void setEnabled(boolean enabled) { this.enabled = enabled; }
    
    public MiddlewareType getMiddlewareType() { return middlewareType; }
    public void setMiddlewareType(MiddlewareType middlewareType) { this.middlewareType = middlewareType; }
    
    public SerializationType getSerializationType() { return serializationType; }
    public void setSerializationType(SerializationType serializationType) { this.serializationType = serializationType; }
    
    public ConsumerMode getConsumerMode() { return consumerMode; }
    public void setConsumerMode(ConsumerMode consumerMode) { this.consumerMode = consumerMode; }
    
    public String getTopicPrefix() { return topicPrefix; }
    public void setTopicPrefix(String topicPrefix) { this.topicPrefix = topicPrefix; }
    
    public boolean isPersistenceEnabled() { return persistenceEnabled; }
    public void setPersistenceEnabled(boolean persistenceEnabled) { this.persistenceEnabled = persistenceEnabled; }
    
    public boolean isCompressionEnabled() { return compressionEnabled; }
    public void setCompressionEnabled(boolean compressionEnabled) { this.compressionEnabled = compressionEnabled; }
    
    public boolean isDeadLetterQueueEnabled() { return deadLetterQueueEnabled; }
    public void setDeadLetterQueueEnabled(boolean deadLetterQueueEnabled) { this.deadLetterQueueEnabled = deadLetterQueueEnabled; }
    
    public boolean isRetryEnabled() { return retryEnabled; }
    public void setRetryEnabled(boolean retryEnabled) { this.retryEnabled = retryEnabled; }
    
    public boolean isTransactionEnabled() { return transactionEnabled; }
    public void setTransactionEnabled(boolean transactionEnabled) { this.transactionEnabled = transactionEnabled; }
    
    public ProducerProperties getProducer() { return producer; }
    public void setProducer(ProducerProperties producer) { this.producer = producer; }
    
    public ConsumerProperties getConsumer() { return consumer; }
    public void setConsumer(ConsumerProperties consumer) { this.consumer = consumer; }
    
    public RetryProperties getRetry() { return retry; }
    public void setRetry(RetryProperties retry) { this.retry = retry; }
    
    public DeadLetterProperties getDeadLetter() { return deadLetter; }
    public void setDeadLetter(DeadLetterProperties deadLetter) { this.deadLetter = deadLetter; }
    
    public MonitorProperties getMonitor() { return monitor; }
    public void setMonitor(MonitorProperties monitor) { this.monitor = monitor; }
    
    public EmailProperties getEmail() { return email; }
    public void setEmail(EmailProperties email) { this.email = email; }
    
    public SmsProperties getSms() { return sms; }
    public void setSms(SmsProperties sms) { this.sms = sms; }
    
    public PushProperties getPush() { return push; }
    public void setPush(PushProperties push) { this.push = push; }
    
    public Map<String, TopicProperties> getTopics() { return topics; }
    public void setTopics(Map<String, TopicProperties> topics) { this.topics = topics; }
}
